Lab 04 - Architektury behawioralne
Lab. 04 - Architektury behawioralne
1. Czym są architektury behawioralne?
Architektury behawioralne to takie podejście do sterowania robotami, gdzie robot wykonuje z góry zaprogramowane zachowania. Ich wygląd i priorytety są ustalane przez programistów.
Na zajęciach skupimy się na drzewach behawioralnych, którego przykład jest widoczny poniżej:
Będziemy korzystać z biblioteki py_trees (link)
i jej rozszerzenia py_trees_ros (link).
Zachowania (Behaviours)
Są to najmniejsze elementy drzewa. Reprezentują najczęściej sprawdzanie warunków albo wykonywanie działań. Np. “Czy obiekt jest chwycony?” albo “Chwyć obiekt jedną ręką”.
Każde zachowanie ma metodę, która jest wywoływana tuż po jego
pierwszym uruchomieniu (initialise), metodę, która jest
wywoływana przy każdym uruchomieniu zachowania (update),
oraz metodę, która jest wywoływana po jego zakończeniu, powodzeniem lub
nie (terminate). Istnieje również metoda setup
wywoływana podczas przygotowywania drzewa.
Poza tym, każde zachowanie ma jeszcze swój status
(SUCCESS, FAILURE, RUNNING oraz
INVALID), a także feedback message, czyli wiadomość
pomagającą śledzić co zachowanie aktualnie robi.
Kompozycje (Composites)
Kierują one sposobem przechodzenia po zachowaniach. W
py_trees mamy dostępne następujące kompozycje:
- Sequence
- wykonuje zachowania po kolei, od pierwszego do ostatniego. Jeżeli
którekolwiek z jego dzieci (ang. child) zakończy się stanem
FAILURE, całość jest przerywana i kończy się stanemFAILURE. Nastepne zachowanie nie jest wykonywane dopóki poprzednie nie zakończy się sukcesem. - Selector
- wykonuje zachowania po kolei, od pierwszego do ostatniego. Różni się
od Sequence tym, że powodzenie jednego z dzieci nie kończy się
niepowodzeniem całości. Wystarczy, że jeden z dzieci zakończy się stanem
SUCCESS, aby Selector zwrócił stanSUCCESS. - Parallel
- wykonuje zachowania równolegle. Istnieje możliwość dowolnego
określenia, kiedy zwracany jest sukces:
- SuccessOnAll - wszystkie dzieci muszą zakończyć się stanem
SUCCESS. - SuccessOnOne - co najmniej jedno dziecko kończy się stanem
SUCCESS. - SuccessOnSelected - zdefiniowany podzbiór dzieci kończy się stanem
SUCCESS.
- SuccessOnAll - wszystkie dzieci muszą zakończyć się stanem
Dekoratory (Decorators)
Inaczej kapelusze (ang. hats), zarządzają działaniem pojedynczych dzieci, modyfikując je w jakiś sposób. Pełna lista jest długa, ale jedne z istotniejszych to:
- EternalGuard
- blokuje wykonywanie zachowania jeżeli warunek nie jest spełniony
(zwraca wtedy
FAILURE). - Inverter
- odwraca zwracany przez zachowanie status.
SUCCESSnaFAILUREi odwrotnie. - Retry
powtarza wywołanie zachowania określoną liczbę razy, aż nie zostanie
zwrócony status
SUCCESS.
Tablice (Blackboards)
Jest to przestrzeń wymiany danych między zachowaniami. Ta koncepcja
najbardziej kłóci się z koncepcjami ROSa (tam node’y komunikują się
przez topici), ale z założenia drzewa behawioralne działają
synchronicznie, a ROS asynchronicznie.
Dlatego, w przypadku takiego sterowania, nie możemy wywoływać żadnych
callbacków. W py_trees_ros zostały utworzone klasy
pozwalająca tworzyć subskrybenta topica, która
synchronicznie, za każdym jej wywołaniem, udostępnia te
dane na tablicy. Mają one różne sposoby działania,
więcej w dokumentacji.
Po co to wszystko?
Uniwersalność
Drzewa behawioralne są szczególnie popularne podczas rozwijania gier. Możliwość stworzenia uniwersalnych zachowań, które dla różnych obiektów można łączyć w różne drzewa (często graficznie) pozwala na dużą uniwersalność stworzonego kodu. Wszelkie systemy z wieloma robotami też z tej zalety mogą korzystać.
Czytelność
Drzewa behawioralne są bardzo łatwe do interpretacji. Biblioteki mają natywnie wbudowane metody podglądu nie tylko architektury drzewa, ale również stanów i feedbacków podczas działania. Przez to również analiza i debugowanie staje się prostsze.
2. Cel zajęć
Celem tych zajęć będzie przygotowanie robota, który będzie realizował drzewo behawioralne zgodnie z założeniami:
- robot kręci się w kółko,
- robot sprawdza jaka jest odległość do przeszkody przed nim (±10°)
- jeżeli do przeszkody przed nim jest więcej niż 3 metry, jedzie do przodu.
Pożądane działanie zostało przedstawione na GIFie na górze instrukcji.
3. Przygotowanie środowiska
Przed przystąpieniem do pracy należy przygotować środowisko: Instrukcja przygotowania środowiska do zajęć.
Domyślnie kontener nosi nazwę ARM_04.
UWAGA! Skrypty po uruchomieniu usuwają kontener o takiej nazwie przed utworzeniem nowego.
Korzystanie z kontenera
Po każdym ponownym uruchomieniu komputera, proszę pamiętać o wywoływaniu:
xhost +local:root
Nowy terminal można dołączyć do kontenera korzystając z polecenia:
docker exec -it ARM_04 bash
ROS_DOMAIN_ID
W przypadku pracy na wielu komputerach w tej samej sieci lokalnej
(eduroam też może tego wymagać), konieczne może być ustawienie
zmiennej środowiskowej ROS_DOMAIN_ID na różnych
wartościach. Należy wybrać dowolną liczbę całkowitą z zakresu 0-100.
Wartość tę należy ustawić w pliku ~/.bashrc:
export ROS_DOMAIN_ID=10 # przykładowa wartość
lub bezpośrednio w terminalu (wtedy będzie obowiązywać tylko w tym terminalu):
export ROS_DOMAIN_ID=10 # przykładowa wartość
Sugerowane jest użycie dwóch ostatnich cyfr numeru IP komputera jako
wartości ROS_DOMAIN_ID, aby uniknąć konfliktów z innymi
użytkownikami w sieci. Aby sprawdzić swój adres IP, można użyć
polecenia:
ip addr show
adres IP będzie widoczny przy interfejsie sieciowym, np.
wlan0 lub eth0.
Wygodne może być dodanie tego exportu do bashrc:
echo 'export ROS_DOMAIN_ID=<wybrana_wartość>' >> ~/.bashrc
4. Uruchomienie symulacji
W tej instrukcji będziemy ponownie wykorzystywać robota TurtleBot3,
tym razem w świecie world1.sdf z paczki
turtlebot3_bt. Można ją uruchomić poleceniem
cd /arm_ws
ros2 launch turtlebot3_bt turtlebot3_world1.launch.py
W przypadku błędów związanych z uruchomieniem symulacji proszę wywołać te polecenia:
source /usr/share/gazebo/setup.bash
source /usr/share/gazebo-11/setup.bash
ros2 launch turtlebot3_bt turtlebot3_world1.launch.py
Początkowo, symulacja uruchamia się ze ścianą oddzielającą robota od reszty pomieszczenia. W ten sposób zasięg skanera w żadnym punkcie nie przekracza 3 metrów.
Możliwe jest usunięcie przedzielającej ściany w gazebo.
Wystarczy zaznaczyć ją kliknięciem myszki i usunąć klawiszem
delete. Wtedy po prawej stronie pomieszczenia skany będą
większe niż 3 metry.
5. Uruchomienie drzewa behawioralnego
Mając uruchomioną symulację (jeszcze z obecną ścianą przedzielającą), możliwe jest uruchomienie node’a drzewa behawioralnego:
ros2 run turtlebot3_bt run_bt.py
W przypadku błędów z uruchomieniem może okazać się konieczne wywołanie poleceń:
apt install -y ros-humble-py-trees-ros
source install/setup.bash
W tej sytuacji robot zacznie kręcić się w kółko i zbierać dane ze skanera, a w terminalu z uruchomionym nodem będzie widoczny aktualna struktura i stan drzewa.
Na ten moment, niezależnie od obecności ściany przedzielającej pomieszczenie, robot będzie robił to samo.
Możliwe jest podejrzenie zawartości Tablicy:
py-trees-blackboard-watcher
6. Zadanie do samodzielnej realizacji
W skrypcie run_bt.py zaznaczono punkty TODO.
W skrypcie behaviours.py należy utworzyć nowe zachowanie
Drive, które wysyła komendę jazdy prosto z prędkością
przekazywaną przez argument vel.
Nastepnie należy tak zmodyfikować skrypt run_bt.py, aby
realizował założenia z punktu 2. Cel
zajęć.
Na eKursy proszę udostępnić:
- skrypt
run_bt.py, z rozszerzeniem zmienionym na.txt, - skrypt
behaviours.py, z rozszerzeniem zmienionym na.txt, - zrzut ekranu terminala node’a z uruchomionym drzewem.
7. Dodatkowe materiały
- Tutorial
py_trees_roswykorzystujący mock robota - Wytłumaczenie drzew behawioralnych w Unreal Engine - ciekawie pokazane działanie drzew, jednocześnie uruchamiane w grze
Autor: Kamil Młodzikowski